import Koa from 'koa';
import { IProxyOption, ProxyContexts } from '../../models';


export class ProxyConfig {

    constructor() {

    }

    static getConfig(options: IProxyOption | IProxyOption[], ctx: Koa.Context): IProxyOption {
        if (!options) {
            return null;
        }
        const currentOptions = Array.isArray(options) ? options : [options];
        let configs = currentOptions;

        if (ctx.header?.host) {
            configs = currentOptions.filter(itemConfig => itemConfig.host === ctx.header.host);
        }
        if (!configs.length) {
            configs = currentOptions.filter(itemConfig => !itemConfig.host);
        }
        const url = ctx.request.url;
        let proxyConfig: IProxyOption = null;
        for (let i = 0, length = configs.length; i < length; i++) {
            const optionItem = configs[i];
            if (ProxyConfig.getMatchResult(optionItem, url)) {
                proxyConfig = optionItem;
                break;
            }
        }
        return proxyConfig;
    }

    /**
     * get url match result
     * @param option match params
     * @param url current url
     * @returns
     */
   static getMatchResult(option: IProxyOption, url = '') {
        const contextResult = ProxyConfig.getMatchParams(option.context, url);
        const excludeResult = ProxyConfig.getMatchParams(option.exclude, url);
        return contextResult && !excludeResult;
    }

    static getMatchParams(params: ProxyContexts, url: string) {
        let result = false;
        try {
            const context = Array.isArray(params) ? params : [params];
            for (let i = 0, length = context.length; i < length; i++) {
                let contextItem = context[i];
                if (!contextItem) {
                    continue;
                }
                if (typeof (contextItem) === 'string') {
                    contextItem = new RegExp(`^${contextItem}[\\s\\S]*$`);
                }
                if (contextItem.test(url)) {
                    result = true;
                    break;
                }
            }
        } catch (error) {
            // TODO
        }
        return result;
    }

}